package com.kaibes.platform.article.db.service;

import java.math.BigInteger;
import java.time.LocalDateTime;
import java.util.List;

import org.springframework.stereotype.Service;

import com.kaibes.core.base.option.NullOptions;
import com.kaibes.orm.core.core.Page;
import com.kaibes.orm.curd.OrderType;
import com.kaibes.orm.curd.Query;
import com.kaibes.orm.curd.QueryBuilder;
import com.kaibes.orm.curd.Select;
import com.kaibes.orm.curd.SelectBuilder;
import com.kaibes.orm.curd.UpdateBuilder;
import com.kaibes.platform.article.db.entity.Article;
import com.kaibes.platform.article.enums.ArticleStatus;
import com.kaibes.platform.article.enums.ArticleType;
import com.kaibes.web.api.ResponseServiceImpl;

@Service
public class ArticleService extends ResponseServiceImpl<Article> {
    
    public BigInteger lastIdById(Integer id) {
        Article temp = getMapper().selectFirst(SelectBuilder.newBuilder()
                .addColumn("id")
                .addQuery(QueryBuilder.newBuilder().lt("id", id).build()).addOrder("id", OrderType.DESC).setSize(1).build());
        if (temp == null) {
            return null;
        } else {
            return temp.getId();
        }
    }
    
    public BigInteger nextIdById(Integer id) {
        Article temp = getMapper().selectFirst(SelectBuilder.newBuilder()
                .addColumn("id")
                .addQuery(QueryBuilder.newBuilder().gt("id", id).build()).addOrder("id", OrderType.ASC).setSize(1).build());
        if (temp == null) {
            return null;
        } else {
            return temp.getId();
        }
    }
    
    public long countToday() {
        return count(QueryBuilder.newBuilder().sql("TO_DAYS(`create_time`) = TO_DAYS(NOW())").build());
    }
    
    public long countYesterday() {
        return count(QueryBuilder.newBuilder().sql("TO_DAYS(NOW()) - TO_DAYS(`create_time`) = 1").build());
    }
    
    public long countByCategoryId(Short categoryId) {
        return count(QueryBuilder.newBuilder().eq("category_id", categoryId).build());
    }
    
    public long countByUserId(Integer userId) {
        return count(QueryBuilder.newBuilder().eq("user_id", userId).build());
    }
    
    public long getCommentCountByCategoryId(Short categoryId) {
        List<Article> articles = list(QueryBuilder.newBuilder().eq("category_id", categoryId).build(), "comment_count");
        long count = 0;
        for (Article article : articles) {
            count += article.getCommentCount();
        }
        return count;
    }
    public boolean isCommentAble(Object id) {
        Article e = getById(id, "comment_able");
        if (e == null) {
            return false;
        } else {
            return e.getCommentAble();
        }
    }
    
    public int plusCount(BigInteger id) {
        return getMapper().update(UpdateBuilder.newBuilder().setValue("view_count+", 1).addQuery(QueryBuilder.newBuilder().eq("id", id).build()).build());
    }
    public int plusCommentCount(BigInteger id) {
        return getMapper().update(UpdateBuilder.newBuilder().setValue("comment_count+", 1).setValue("comment_time", LocalDateTime.now()).addQuery(QueryBuilder.newBuilder().eq("id", id).build()).build());
    }
    public int minusCommentCount(BigInteger id) {
        return getMapper().update(UpdateBuilder.newBuilder().setValue("comment_count-", 1).addQuery(QueryBuilder.newBuilder().eq("id", id).build()).build());
    }
    
    public String getTitleById(BigInteger id) {
        return getById(id, "title").getTitle();
    }
    public Article getTitleUserIdById(BigInteger id) {
        return getById(id, "title", "user_id");
    }
    public Article getTitleId(BigInteger id) {
        return getById(id, "id", "title");
    }
    public Integer getUserIdById(BigInteger id) {
        return NullOptions.returnInteger(getById(id, "user_id"), a->a.getUserId());
    }
    
    public List<Article> listTitleIdThumbnailContentHot(int count) {
        Select select = SelectBuilder.newBuilder().addColumn("id").addColumn("title").addColumn("thumbnail").addColumn("content").addOrder("view_count", OrderType.DESC).setSize(count).build();
        return getMapper().select(select);
    }
    
    public List<Article> listTitleIdHot(int count) {
        Select select = SelectBuilder.newBuilder().addColumn("id").addColumn("title").addOrder("view_count", OrderType.DESC).setSize(count)
                .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("status", ArticleStatus.PUBLISH).build()).build();
        return getMapper().select(select);
    }
    public List<Article> listTitleIdNew(int count) {
        Select select = SelectBuilder.newBuilder().addColumn("id").addColumn("title").addOrder("create_time", OrderType.DESC).setSize(count)
                .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("status", ArticleStatus.PUBLISH).build()).build();
        return getMapper().select(select);
    }
    public List<Article> listTitleIdThumbnailHot(int count) {
        Select select = SelectBuilder.newBuilder().addColumn("id").addColumn("title").addColumn("thumbnail").addOrder("view_count", OrderType.DESC).setSize(count)
                .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("status", ArticleStatus.PUBLISH).build()).build();
        return getMapper().select(select);
    }
    
    public List<Article> list(int count) {
        Select select = SelectBuilder.newBuilder()
                .addQuery(QueryBuilder.newBuilder().eq("status", ArticleStatus.PUBLISH).build())
                .addOrder("id", OrderType.DESC).setSize(count).build();
        return getMapper().select(select);
    }
    public List<Article> listByOrderViewCount(int count) {
        Select select = SelectBuilder.newBuilder()
                .addQuery(QueryBuilder.newBuilder().eq("status", ArticleStatus.PUBLISH).build())
                .addOrder("view_count", OrderType.DESC).setSize(count).build();
        return getMapper().select(select);
    }
    public List<Article> listByOrderCommentTime(int count) {
        Select select = SelectBuilder.newBuilder()
                .addQuery(QueryBuilder.newBuilder().eq("status", ArticleStatus.PUBLISH).build())
                .addOrder("comment_time", OrderType.DESC).setSize(count).build();
        return getMapper().select(select);
    }
    public List<Article> listTops(int count) {
        Select select = SelectBuilder.newBuilder()
                .addQuery(QueryBuilder.newBuilder().eq("status", ArticleStatus.PUBLISH).eq("top", true).build())
                .addOrder("id", OrderType.DESC).setSize(count).build();
        return getMapper().select(select);
    }

    public Page<Article> pageAscByStatusAndCategoryId(int pageIndex, int pageSize, ArticleStatus status, Short categoryId) {
        Query query;
        if (status == null) {
            query = QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("category_id", categoryId).build();
        } else {
            query = QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("status", status.toString()).eq("category_id", categoryId).build();
        }
        Select select = SelectBuilder.newBuilder().addOrder("id", OrderType.ASC).addQuery(query).build();
        return getMapper().page(select, pageIndex, pageSize);
    }
    
    public Page<Article> pageAscByStatusAndTag(int pageIndex, int pageSize, ArticleStatus status, String tag) {
        Query query;
        if (status == null) {
            query = QueryBuilder.newBuilder().eq("type", ArticleType.POST).like("tags", tag).build();
        } else {
            query = QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("status", status.toString()).like("tags", tag).build();
        }
        Select select = SelectBuilder.newBuilder().addOrder("id", OrderType.ASC).addQuery(query).build();
        return getMapper().page(select, pageIndex, pageSize);
    }
    
    public Page<Article> pageAscByStatusAndSearch(int pageIndex, int pageSize, ArticleStatus status, String search) {
        Select select;
        if (status == null) {
            select = SelectBuilder.newBuilder().addOrder("id", OrderType.ASC)
                    .addQuery(QueryBuilder.newBuilder().inSelect("user_id", 
                                SelectBuilder.newBuilder().setTableName("user").addColumn("id")
                                    .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).like("nickname", search).build())
                                .build())
                            .build())
                    .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).like("title", search).build()).build();
        } else {
            select = SelectBuilder.newBuilder().addOrder("id", OrderType.ASC)
                    .addQuery(QueryBuilder.newBuilder().eq("status", status.toString()).inSelect("user_id", 
                            SelectBuilder.newBuilder().setTableName("user").addColumn("id")
                                .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).like("nickname", search).build())
                            .build())
                        .build())
                    .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("status", status.toString()).like("title", search).build()).build();
        }
        return getMapper().page(select, pageIndex, pageSize);
    }
    
    public Page<Article> pageAscByStatus(int pageIndex, int pageSize, ArticleStatus status) {
        if (status == null) {
            return pageAsc(pageIndex, pageSize, "id");
        } else {
            Select select = SelectBuilder.newBuilder().addOrder("id", OrderType.ASC)
                    .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("status", status.toString()).build()).build();
            return getMapper().page(select, pageIndex, pageSize);
        }
    }
    
    public Page<Article> pageByCreateTimeAsc(int pageIndex, int pageSize) {
        Select select = SelectBuilder.newBuilder().addColumn("id").addColumn("title").addOrder("create_time", OrderType.ASC)
                .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("status", ArticleStatus.PUBLISH).build())
                .build();
        return getMapper().page(select, pageIndex, pageSize);
    }
    public Page<Article> pageByCreateTimeDesc(int pageIndex, int pageSize) {
        Select select = SelectBuilder.newBuilder().addColumn("id").addColumn("title").addOrder("create_time", OrderType.DESC)
                .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("status", ArticleStatus.PUBLISH).build())
                .build();
        return getMapper().page(select, pageIndex, pageSize);
    }
    public Page<Article> pageByViewCountAsc(int pageIndex, int pageSize) {
        Select select = SelectBuilder.newBuilder().addColumn("id").addColumn("title").addOrder("view_count", OrderType.ASC)
                .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("status", ArticleStatus.PUBLISH).build())
                .build();
        return getMapper().page(select, pageIndex, pageSize);
    }
    public Page<Article> pageByViewCountDesc(int pageIndex, int pageSize) {
        Select select = SelectBuilder.newBuilder().addColumn("id").addColumn("title").addOrder("view_count", OrderType.DESC)
                .addQuery(QueryBuilder.newBuilder().eq("type", ArticleType.POST).eq("status", ArticleStatus.PUBLISH).build())
                .build();
        return getMapper().page(select, pageIndex, pageSize);
    }
    
}
